package asteroids.model.programs.expressions;

import asteroids.model.Ship;


public class ExprStringEvaluator implements ExprEvaluator<String> {
	
	public ExprStringEvaluator(Ship ship) {
		this.ship = ship;
		ebe = new ExprBoolEvaluator(ship);
		ede = new ExprDoubleEvaluator(ship);
	}
	
	private ExprBoolEvaluator getEBE() {
		return ebe;
	}

	private final ExprBoolEvaluator ebe;
	
	private ExprDoubleEvaluator getEDE() {
		return ede;
	}

	private final ExprDoubleEvaluator ede;
	
	public Ship getShip(){
		return ship;
	}

	private final Ship ship;

	@Override
	public String evaluate(And and) {
		boolean result = and.accept(getEBE());
		return "And at line "+and.getLine()+", column "+and.getColumn()+" with value: "+result+".";
	}

	@Override
	public String evaluate(Or or) {
		boolean result = or.accept(getEBE());
		return "Or at line "+or.getLine()+", column "+or.getColumn()+" with value: "+result+".";
	}

	@Override
	public String evaluate(LessThan lt) {
		boolean result = lt.accept(getEBE());
		return "LessThan at line "+lt.getLine()+", column "+lt.getColumn()+" with value: "+result+".";
	}

	@Override
	public String evaluate(GreaterThan gt) {
		boolean result = gt.accept(getEBE());
		return "GreaterThan at line "+gt.getLine()+", column "+gt.getColumn()+" with value: "+result+".";
	}

	@Override
	public String evaluate(Equality eq) {
		boolean result = eq.accept(getEBE());
		return "Equality at line "+eq.getLine()+", column "+eq.getColumn()+" with value: "+result+".";
	}

	@Override
	public String evaluate(Add add) {
		double result = add.accept(getEDE());
		return "Add at line "+add.getLine()+", column "+add.getColumn()+" with value: "+result+".";
	}

	@Override
	public String evaluate(Subtract sub) {
		double result = sub.accept(getEDE());
		return "Subtract at line "+sub.getLine()+", column "+sub.getColumn()+" with value: "+result+".";
	}

	@Override
	public String evaluate(Division div) {
		double result = div.accept(getEDE());
		return "Division at line "+div.getLine()+", column "+div.getColumn()+" with value: "+result+".";
	}

	@Override
	public String evaluate(Multiply mul) {
		double result = mul.accept(getEDE());
		return "Multiply at line "+mul.getLine()+", column "+mul.getColumn()+" with value: "+result+".";
	}

	@Override
	public String evaluate(DoubleLiteral d) {
		return "DoubleLiteral at line "+d.getLine()+", column "+d.getColumn()+" with value: "+d.getD()+".";
	}

	@Override
	public String evaluate(BooleanLiteral b) {
		return "BooleanLiteral at line "+b.getLine()+", column "+b.getColumn()+" with value: "+b.getB()+".";
	}

	@Override
	public String evaluate(Not not) {
		boolean result = not.accept(getEBE());
		return "Not at line "+not.getLine()+", column "+not.getColumn()+" with value: "+result+".";
	}

	@Override
	public String evaluate(Sqrt sqrt) {
		double result = sqrt.accept(getEDE());
		return "Sqrt at line "+sqrt.getLine()+", column "+sqrt.getColumn()+" with value: "+result+".";
	}

	@Override
	public String evaluate(Sin sin) {
		double result = sin.accept(getEDE());
		return "Sin at line "+sin.getLine()+", column "+sin.getColumn()+" with value: "+result+".";
	}

	@Override
	public String evaluate(Cos cos) {
		double result = cos.accept(getEDE());
		return "Cos at line "+cos.getLine()+", column "+cos.getColumn()+" with value: "+result+".";
	}

	@Override
	public String evaluate(GetDirection getDir) {
		double result = getDir.accept(getEDE());
		return "GetDirection at line "+getDir.getLine()+", column "+getDir.getColumn()+" with value: "+result+".";
	}

	@Override
	public String evaluate(Self self) {
		return "Self at line "+self.getLine()+", column "+self.getColumn()+" with value: "+getShip().toString()+".";
	}

	@Override
	public String evaluate(GetX getX) {
		double result = getX.accept(getEDE());
		return "GetX at line "+getX.getLine()+", column "+getX.getColumn()+" with value: "+result+".";
	}

	@Override
	public String evaluate(GetY getY) {
		double result = getY.accept(getEDE());
		return "GetY at line "+getY.getLine()+", column "+getY.getColumn()+" with value: "+result+".";
	}

	@Override
	public String evaluate(GetVX getVX) {
		double result = getVX.accept(getEDE());
		return "GetVX at line "+getVX.getLine()+", column "+getVX.getColumn()+" with value: "+result+".";
	}

	@Override
	public String evaluate(GetVY getVY) {
		double result = getVY.accept(getEDE());
		return "GetVY at line "+getVY.getLine()+", column "+getVY.getColumn()+" with value: "+result+".";
	}

	@Override
	public String evaluate(GetRadius getRadius) {
		double result = getRadius.accept(getEDE());
		return "GetRadius at line "+getRadius.getLine()+", column "+getRadius.getColumn()+" with value: "+result+".";
	}

	@Override
	public String evaluate(Variable var) {
		String key = var.getName();
		Expression rhs = getShip().getProgram().getAssignment(key);
		String result = getShip().getProgram().getType(key).getString(rhs, getShip());
		return "Variable at line "+var.getLine()+", column "+var.getColumn()+" with value: "+result+".";
	}

	@Override
	public String evaluate(EntityLiteral e) {
		return e.getGameObject().toString();
	}

	@Override
	public String evaluate(Null null1) {
		return "null";
	}

}
